package com.lry.pda.bottom.c.frontend;

import com.lry.pda.bottom.c.backend.Interpretor;
import com.lry.pda.bottom.c.backend.MemoryHeap;
import com.lry.pda.bottom.c.backend.code.CodeTreeBuilder;
import com.lry.pda.bottom.c.backend.executor.ExecutorFactory;
import com.lry.pda.bottom.c.backend.type.Symbol;
import com.lry.pda.bottom.c.backend.type.TypeSystem;

import java.util.Map;
import java.util.Stack;

public class LRValueParser {

    private Lexer lexer;
    public int nestingLevel;
    public String relOperatorText;
    public String compoundAssignText;
    public String scope = Symbol.SCOPE;
    private Stack<Integer> stack = new Stack<>();//存储节点编号的状态堆栈
    public Stack<Object> valueStack = new Stack<>();

    private TypeSystem typeSystem = TypeSystem.getSelf();
    private Map<Integer, Map<Integer,Integer>> lrTable;
    private int inputToken;
    public String text;
    public Object attributeForParentNode;
    private CodeTreeBuilder codeTreeBuilder = CodeTreeBuilder.getSelf();

    public LRValueParser(Lexer lexer){
        this.lexer = lexer;
        codeTreeBuilder.setParser(this);
    }

    private void init(){
        System.out.println("\nInput string for parsing:");
        this.lexer.clear();
        this.lexer.input();
        this.lexer.advance();
        this.typeSystem.clear();
        this.inputToken = CTokenType.EXT_DEF_LIST.ordinal();
        this.valueStack.clear();
        codeTreeBuilder.clear();
        this.valueStack.push(null);
        this.text = null;
        this.scope = Symbol.SCOPE;
        this.nestingLevel = 0;
        this.relOperatorText = null;
        this.compoundAssignText = null;
        this.attributeForParentNode = null;
        this.stack.clear();
        MemoryHeap.getSelf().clear();
        this.stack.push(0);//初始为0节点
    }

    private Integer getAction(Integer currentState, Integer currentInput) {
        Map<Integer, Integer> jump = lrTable.get(currentState);
        if (jump != null) {
            Integer next = jump.get(currentInput);
            if (next != null) {
                return next;
            }
        }
        return null;
    }

    public void parse(){
        init();
        Integer action = null;
        while(true){
            action = getAction(stack.peek(), inputToken);

            if (action == null) {
                System.out.println("Shift for input: " + CTokenType.values()[inputToken].toString());
                //解析出错
                System.err.println("The input is denied");
                parse();
                return;
            }

            if(action==0){
                System.out.println("The input can be accepted");

                System.out.println("开始解释执行c程序");

                Interpretor interpretor = Interpretor.getSelf();
                interpretor.execute(codeTreeBuilder.getTreeRoot());

                parse();
                return;
            }else if(action > 0){
                //shift 操作
                stack.push(action);//压入下一个节点编号
                text = lexer.yytext;
                if (inputToken == CTokenType.RELOP.ordinal()) {
                    relOperatorText = text;
                }
                if (inputToken == CTokenType.COMPOUND_ASSIGN.ordinal()) {
                    compoundAssignText = text;
                }
                if (CTokenType.isTerminal(inputToken)) {
                    System.out.println("Shift for input: " + CTokenType.values()[inputToken].toString());
                    takeActionForShift(inputToken);
                    lexer.advance();
                    valueStack.push(text);
                }
                inputToken = lexer.lookAhead;
            }else {
                int number = - action;
                State state = StateManager.getSelf().getState(stack.peek());
                Production product = state.getProduction(number);
                System.out.println("reduce by product: ");
                product.print();
                takeActionForReduce(product);

                inputToken = product.getLeft();
                int rightSize = product.getDotPos();
                while (rightSize > 0) {
                    stack.pop();
                    valueStack.pop();
                    rightSize--;
                }
                valueStack.push(attributeForParentNode);
            }
        }
    }

    private void takeActionForShift(int token) {
        if (token == CTokenType.LP.ordinal() || token == CTokenType.LC.ordinal()) {
            nestingLevel++;
        }
        if (token == CTokenType.RP.ordinal() || token == CTokenType.RC.ordinal()) {
            nestingLevel--;
        }
    }

    private void takeActionForReduce(Production product) {
        if(null!=product.getConsumer()){
            product.getConsumer().accept(null);
        }
        codeTreeBuilder.buildCodeTree(product.getNumber(),text);
    }

    public static void main(String[] args) {
        LRValueParser lrParser = new LRValueParser(new Lexer());

        Grammar grammar = Grammar.getSelf();
        grammar.setParser(lrParser);

        ProductionManager productionManager = ProductionManager.getSelf();
        productionManager.init();

        StateManager stateManager = StateManager.getSelf();
        stateManager.buildTransitionStateMachine();

        lrParser.lrTable = stateManager.getLRTable();
        lrParser.parse();
    }
}
